package com.whately.core.base.event;

import com.google.common.collect.Maps;
import com.whately.core.base.exception.ServiceException;
import com.whately.core.base.model.RecorderModel;
import com.whately.core.base.selfconfig.SelfDefineConfigWhLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class RecorderOperateHandler {
    @Autowired
    private SelfDefineConfigWhLog selfDefineConfigWhLog;

    @Autowired
    public List<IRecorderOperate> handlerList;

    private Map<Integer, IRecorderOperate>  handlerMap;


    @PostConstruct
    public void init(){
        Map<Integer, IRecorderOperate>  map = Maps.newTreeMap();
        if(handlerList!=null){
            for(IRecorderOperate operate:handlerList){
                //排除的处理器
                if(StringUtils.isNotBlank(selfDefineConfigWhLog.getExcludeHandlerCode())){
                    String excludeCode = selfDefineConfigWhLog.getExcludeHandlerCode()+",";
                    if(excludeCode.contains(operate.getHandlerCode()+",")){
                        continue;
                    }
                }
                //做一次检查，查看表是否存在
                if(operate.getHandlerCode() == 888){
                    try{
                        operate.testQuery();
                    }catch (Exception e){

                        //表未建，直接忽略改处理器
                        if(e instanceof ServiceException){
                            ServiceException se = (ServiceException)e;
                            if(se.getCode()==888){
                                log.error("handler of log for RecorderOperateByDbImpl not find table! so handler code 888 ignore");
                                continue;
                            }
                        }else{
                            log.error("handler code 888 error",e);
                        }

                    }

                }

                if(!map.containsKey(operate.getHandlerCode())){
                    map.put(operate.getHandlerCode(),operate);
                }else{
                    log.error("found duplicate handler code {},ignore class {}",operate.getHandlerCode(),operate);
                }
            }
            handlerMap =map;
        }

        log.info("wh log handler init ok {}",handlerMap);
    }

    /**
     * 注册监听实现方法
     */
    @EventListener
    @Async
    public void handlerRecord(RecorderOperateEvent event) {

        //获取注册用户对象
        RecorderOperateBean bean = event.getBean();
        RecorderModel model = bean.getRecorderModel();
        int handlerType = bean.getHandlerType();
        int[] handlerCodeArray = bean.getHandlerCode();


        if(handlerType==-1){
            for (Map.Entry<Integer, IRecorderOperate> entry : handlerMap.entrySet()) {
                entry.getValue().record(model);
            }
        }else if(handlerType==0||handlerCodeArray==null||handlerCodeArray.length<=0){
            //从字典中取优先级最大的（number 最小的值），处理后就退出。
            Iterator<Map.Entry<Integer, IRecorderOperate>> it = handlerMap.entrySet().iterator();
            while(it.hasNext()){
                Map.Entry<Integer, IRecorderOperate> entry = it.next();
                IRecorderOperate highLs = entry.getValue();
                try{
                    highLs.record(model);
                    break;
                }catch (Exception e){
                    log.error("dealer log error ",e);
                    //if(highLs.getHandlerCode() == 888){
                        //数据库没有添加表，则把dealer 删除
                        //it.remove();//使用迭代器的remove()方法删除元素
                    //}
                }
            }

        }else{
            for(int handlerCode:handlerCodeArray){
                IRecorderOperate operate = handlerMap.get(handlerCode);
                if(operate!=null){
                    try{
                        operate.record(model);
                    }catch (Exception e){
                        log.error("dealer log error ",e);
                    }

                }
            }

        }


    }
}
